package bat.crimea.ua.maven.plugin.increment;

import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;

import java.lang.reflect.Field;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * <p/>
 * <p/>
 * Original Author:   <a href="mailto:Alexey Batyuta <alexey.batyuta@gmail.com>">Alexey Batyuta</a><br/>
 * Created Date:     Dec 21, 2010 <br/>
 * Created Time:     12:36:06 PM <br/>
 * <p/>
 * $Id: ValueItem.java 1 2010-12-22 10:02:34Z Alexey.Batyuta $
 * <p/>
 * $Author: Alexey.Batyuta $
 * $Date: 2010-12-22 10:02:34 +0000 (Wed, 22 Dec 2010) $
 * $Rev: 1 $
 * $URL: http://maven-increment-plugin.googlecode.com/svn/tags/maven-increment-plugin-1.21/src/main/java/bat/crimea/ua/maven/plugin/increment/ValueItem.java $
 */
public class ValueItem {
    /**
     * @parameter property="value" description="Value"
     * @required
     */
    private String _value;
    /**
     * @parameter property="valueClassName" description="Value .class"
     * @required
     */
    private String _valueClassName;
    /**
     * @parameter property="dateInputFormat" expression="${maven.build.timestamp.format}" default="${maven.build.timestamp.format}" description="Date format patern for input value"
     * @required
     */
    private String _dateInputFormat;
    /**
     * @parameter property="dateOutputFormat" expression="${maven.build.timestamp.format}" default-value="${maven.build.timestamp.format}" description="Date format patern for output value"
     * @required
     */
    private String _dateOutputFormat;
    /**
     * @parameter property="incrementValue" description="Increment value"
     * @required
     */
    private String _incrementValue;
    /**
     * @parameter property="incrementDatePeriod" description="Increment type for java.util.Date value, see: java.util.Calendar#add(int, int)"
     */
    private String _incrementDatePeriod;
    /**
     * @parameter property="outputPropertyName" default-value="maven.increment.plugin.result"  description="Output property name"
     */
    private String _outputPropertyName;

    private IncrementMojo incrementMojo;
    private String defaultDateFormat = null;
    protected static final Calendar CALENDAR = new GregorianCalendar();

    protected static String DEFAULT_DATE_FORMAT = "maven.build.timestamp.format";
    protected static String DEFAULT_OUTPUT_PROPERTY_NAME = "maven.increment.plugin.result";

    public ValueItem() {
    }

    public ValueItem(IncrementMojo incrementMojo) {
        init(incrementMojo);
    }

    public void setValue(String value) {
        this._value = value;
    }

    public void setValueClassName(String valueClassName) {
        this._valueClassName = valueClassName;
    }

    public void setDateInputFormat(String dateInputFormat) {
        this._dateInputFormat = dateInputFormat;
    }

    public void setDateOutputFormat(String dateOutputFormat) {
        this._dateOutputFormat = dateOutputFormat;
    }

    public void setIncrementDatePeriod(String incrementDatePeriod) {
        this._incrementDatePeriod = incrementDatePeriod;
    }

    public void setIncrementValue(String incrementValue) {
        this._incrementValue = incrementValue;
    }

    public void setIncrementMojo(IncrementMojo incrementMojo) {
        this.incrementMojo = incrementMojo;
    }

    public void setOutputPropertyName(String outputPropertyName) {
        this._outputPropertyName = outputPropertyName;
    }

    public MavenProject getMavenProject() {
        return incrementMojo._project;
    }

    public String getValue() {
        return _value;
    }

    protected String getValueClassName() {
        return _valueClassName;
    }

    public Class getValueClass() {
        Class result = null;
        try {
            result = getClass().getClassLoader().loadClass(getValueClassName());
        } catch (ClassNotFoundException e) {
            getLog().error(e);
        }
        return result;
    }

    private Log getLog() {
        return incrementMojo.getLog();
    }

    public String getDateInputFormat() {
        return getDateFormat(_dateInputFormat);
    }

    public String getDateOutputFormat() {
        return getDateFormat(_dateOutputFormat);
    }

    public String getIncrementValue() {
        return _incrementValue;
    }

    public String getIncrementDatePeriod() {
        return _incrementDatePeriod;
    }

    public String getOutputPropertyName() {
        if (null == _outputPropertyName || _outputPropertyName.trim().length() == 0) {
            setOutputPropertyName(DEFAULT_OUTPUT_PROPERTY_NAME);
        }
        return _outputPropertyName;
    }

    public void init(IncrementMojo mojo) {
        setIncrementMojo(mojo);
    }

    private String getDateFormat(String dateFormat) {
        if (null == dateFormat || dateFormat.trim().length() == 0) {
            dateFormat = getDefaultDateFormat();
        }
        return dateFormat;
    }

    protected String getDefaultDateFormat() {
        if (null == defaultDateFormat) {
            defaultDateFormat = getMavenProject().getProperties().getProperty(DEFAULT_DATE_FORMAT);
        }
        return defaultDateFormat;
    }

    public int getPeriod() {
        getLog().debug("Start: getPeriod");
        int result = Calendar.DAY_OF_YEAR;
        try {
            getLog().debug("Try to get time period (getField)");
            final Field field = getCalendar().getClass().getField(getIncrementDatePeriod());
            getLog().debug("Tried to get time period");
            result = field.getInt(getCalendar());
        } catch (NoSuchFieldException e) {
            getLog().error(e);
        } catch (IllegalAccessException e) {
            getLog().error(e);
        }
        getLog().debug("End: getPeriod; result = " + result);
        return result;
    }

    public Date getValueAsDate() {
        Date dDate = null;
        try {
            final SimpleDateFormat simpleInputDateFormat = new SimpleDateFormat(getDateInputFormat());
            dDate = simpleInputDateFormat.parse(getValue());
            getLog().debug("Date parsed successfully");
        } catch (ParseException e) {
            getLog().error(e);
        }
        return dDate;
    }

    private Number getIncrementValueAsNumber(String value) {
        Number incrementValue = 0;
        try {
            incrementValue = NumberFormat.getInstance().parse(value);
            getLog().debug("Date incrementValue successfully");
        } catch (ParseException e) {
            getLog().error(e);
        }
        return incrementValue;
    }

    public int getIncrementValueAsInt() {
        return getIncrementValueAsNumber(getIncrementValue()).intValue();
    }

    public int getValueAsInt() {
        return getIncrementValueAsNumber(getValue()).intValue();
    }

    public Calendar getCalendar() {
        return CALENDAR;
    }

    public String process() {
        String result = null;
        final Class valueClass = getValueClass();
        if (Date.class == valueClass) {
            result = dateProcess();
        } else if (Integer.class == valueClass) {
            result = integerProcess();
        }
        return result;
    }

    public String integerProcess() {
        return Integer.toString(getValueAsInt() + getIncrementValueAsInt());
    }

    public String dateProcess() {
        final SimpleDateFormat simpleOutputDateFormat = new SimpleDateFormat(getDateOutputFormat());
        Date dDate = getValueAsDate();
        getCalendar().setTime(dDate);
        getCalendar().add(getPeriod(), getIncrementValueAsInt());
        dDate = getCalendar().getTime();
        return simpleOutputDateFormat.format(dDate);
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("value = ").append(_value).append("; ");
        sb.append("valueClass = ").append(_valueClassName).append("; ");
        sb.append("incrementValue = ").append(_incrementValue).append("; ");
        sb.append("incrementDatePeriod = ").append(_incrementDatePeriod).append("; ");
        sb.append("dateInputFormat = ").append(_dateInputFormat).append("; ");
        sb.append("dateOutputFormat = ").append(_dateOutputFormat).append("; ");
        sb.append("outputPropertyName = ").append(_outputPropertyName);
        return sb.toString();
    }
}
